﻿/******************************************************************
 *Company: http://www.xiaomutech.com/
 *fileName : %{Cpp:License:FileName} --- %{Cpp:License:ClassName}
 *Auth       : yhni (QQ:393320854)
 *Create    : 2022/1/24
 *Description   :
 *Histroy:
 *<Auth>    <Date>        <Ver>        <Content>
 *         2022/1/24
 *******************************************************************/
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "logindialog.h"
#include "qttools.h"

#include <QPainter>
#include <QKeyEvent>
#include <QTime>
#include <QDebug>
#include <QMessageBox>
#include <QMouseEvent>
#include <QKeyEvent>

#define TEST_UI         1

MainWindow::MainWindow(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    m_cardIndex = 0;
    m_cardSize = 54;

    m_timer = new QTimer(this);
    m_timer->setInterval(50);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(sltPickCard()));

    ui->widgetPlayBottom->setAreaType(AreaBottom);
    ui->widgetCardShow->setAreaType(AreaTop);
    ui->widgetAreaCenter->setAreaType(AreaCenter);
    ui->widgetPlayLeft->setAreaType(AreaLeft);
    ui->widgetPlayRight->setAreaType(AreaRight);
    connect(ui->widgetPlayBottom, SIGNAL(playCards(HandType, CardList)), this, SLOT(sltPlayCards(HandType, CardList)));
    connect(ui->widgetPlayLeft, SIGNAL(playCards(HandType, CardList)), this, SLOT(leftPlayCars(HandType, CardList)));
    connect(ui->widgetPlayRight, SIGNAL(playCards(HandType, CardList)), this, SLOT(rightPlayCars(HandType, CardList)));

    m_tcpClient = new QTcpSocket(this);
    connect(m_tcpClient, SIGNAL(readyRead()), this, SLOT(sltSocketRead()));
    connect(m_tcpClient, SIGNAL(connected()), this, SLOT(sltSocketConneced()));
    connect(m_tcpClient, SIGNAL(disconnected()), this, SLOT(sltSockeDisconneced()));
    m_tcpClient->connectToHost("192.168.2.126", 10000);

    ui->stackedWidget->setCurrentIndex(0);

    m_alarmClock = new AlarmClock(this);
    m_alarmClock->hide();
    connect(m_alarmClock, SIGNAL(timeout()), this, SLOT(sltAlarmTimeout()));

    m_animation = new QPropertyAnimation(this, "cardpos");
    m_animation->setDuration(45);
    m_animation->setLoopCount(1);

    m_animationWidget = new AnimationWidget(this);
    m_animationWidget->hide();
    initCardPixs();
}

MainWindow::~MainWindow()
{
    delete ui;
}

/**
 * @brief MainWindow::getPackHeader
 * @param len
 * @param type: 0/进入房间,1/离开,2/准备,3/叫分,4/发牌,5/出牌,6/结算
 * @return
 */
QByteArray MainWindow::getPackHeader(quint8 type, int len)
{
    QByteArray buffer;
    buffer.resize(8 + len);
    buffer[0] = 0xAE;           // 包头
    buffer[1] = len;            // 长度
    buffer[2] = type;           // type
    quint16 id = ui->widgetPlayBottom->getUserId();
    buffer[3] = (id >> 8) & 0xff;
    buffer[4] = id & 0xff;
    buffer[5] = ui->widgetPlayBottom->getOrder();
    buffer[6] = ui->widgetPlayBottom->isReady();
    buffer[7] = ui->widgetPlayBottom->getRole();
    return buffer;
}

void MainWindow::transToSocket(const QByteArray &_data)
{
    if (NULL != m_tcpClient && m_tcpClient->state() == QTcpSocket::ConnectedState) {
        m_tcpClient->write(_data);
    }
}

void MainWindow::parseBuffer(const QByteArray &_data)
{
    uchar len = _data[1];
    uchar type = _data[2];
    quint16 id = _data.mid(3, 2).toHex().toUShort(0, 16);

    switch (type) {
    case EnterIn: {
        quint8 order = ui->widgetPlayBottom->getOrder();

        uchar next = order + 1;
        if (next > 3) next = 1;

        uchar prev = order - 1;
        if (prev == 0) prev = 3;

        for (int i = 0; i < len; i += 4) {
            QByteArray temp = _data.mid(8 + i, 4);
            quint16 _id = temp.mid(0, 2).toHex().toUShort(0, 16);
            quint8 _order = temp[2];
            bool _ready = (1 == temp[3]);
            if (ui->widgetPlayBottom->getUserId() == _id) continue;

            if (next == _order && !ui->widgetPlayRight->getUserId()) {
                ui->widgetPlayRight->setUserId(_id);
                ui->widgetPlayRight->setOrder(_order);
                ui->widgetPlayRight->setReady(_ready);
            }

            if (prev == _order && !ui->widgetPlayLeft->getUserId()) {
                ui->widgetPlayLeft->setUserId(_id);
                ui->widgetPlayLeft->setOrder(_order);
                ui->widgetPlayLeft->setReady(_ready);
            }
        }
    }
        break;
    case Exit: {
        if (id == ui->widgetPlayLeft->getUserId()) {
            ui->widgetPlayLeft->setReady(false);
            ui->widgetPlayLeft->setUserId(0);
        } else if (id == ui->widgetPlayRight->getUserId()) {
            ui->widgetPlayRight->setReady(false);
            ui->widgetPlayRight->setUserId(0);
        }
    }
        break;
    case Ready: {
        bool isReady = ((uchar)_data[8] == 1);
        quint8 order = _data[5];

        if (order == ui->widgetPlayLeft->getOrder()) {
            ui->widgetPlayLeft->setReady(isReady);
        } else if (order == ui->widgetPlayRight->getOrder()) {
            ui->widgetPlayRight->setReady(isReady);
        }

        if (ui->widgetPlayBottom->isReady() &&
                ui->widgetPlayLeft->isReady() &&
                ui->widgetPlayRight->isReady())
        {
            if (0x01 == ui->widgetPlayBottom->getOrder()) {
                QMessageBox::information(this, "提示", QString("我是主机: %1").arg(ui->widgetPlayBottom->getUserId()));
                initCards();
            }
        }
    }
        break;
    case Call:
    {
        quint8 order = _data[8];
        quint8 ready = _data[9]; // 1已经叫完了/0正在抢分
        ui->widgetCardShow->setReady(ready);
        if (ready) {
            ui->stackedWidget->setVisible(false);
            break;
        }

        if (order == ui->widgetPlayBottom->getOrder()) {
            ui->stackedWidget->setCurrentIndex(1);
            ui->stackedWidget->setVisible(true);
        }
    }
        break;
    case SendCard: {
        m_cardSize--;
        quint8 order = _data[5];
        if (CardTypeSize == len) {
            CardType _card;
            memcpy((char *)&_card, _data.mid(8, CardTypeSize).data(), CardTypeSize);
            if (order == ui->widgetPlayLeft->getOrder()) {
                ui->widgetPlayLeft->addCard(new QCard(_card, m_cardPix.value(_card)));
            } else if (order == ui->widgetPlayBottom->getOrder()) {
                ui->widgetPlayBottom->addCard(new QCard(_card, m_cardPix.value(_card)));
            } else if (order == ui->widgetPlayRight->getOrder()) {
                ui->widgetPlayRight->addCard(new QCard(_card, m_cardPix.value(_card)));
            }
        }
        else if ((CardTypeSize * 3) == len) {
            ui->widgetCardShow->setReady(false);
            for (int i = 0; i < len; i += CardTypeSize) {
                CardType _card;
                memcpy((char *)&_card, _data.mid(8 + i, CardTypeSize).data(), CardTypeSize);
                ui->widgetCardShow->addCard(new QCard(_card, m_cardPix.value(_card)));
            }
        }
    }
        break;
    case PlayCard: {
        int offset = sizeof(CardType);
        quint8 order = _data[5];
        quint8 handle = _data[8];
        QList<QCard*> cards;
        for (int i = 9; i < _data.length(); i += offset) {
            CardType _card;
            memcpy((char *)&_card, _data.mid(i, offset).data(), offset);
            cards.push_back(new QCard(_card, m_cardPix.value(_card)));
        }

        if (order == ui->widgetPlayLeft->getOrder()) {
            ui->widgetPlayLeft->remove(cards);
        }  else if (order == ui->widgetPlayRight->getOrder()) {
            ui->widgetPlayRight->remove(cards);
        }
        ui->widgetAreaCenter->addCards(cards);

        if (handle == ui->widgetPlayBottom->getOrder()) {
            ui->stackedWidget->setCurrentIndex(2);
            ui->stackedWidget->setVisible(true);
        }
    }
        break;
    default:
        break;
    }
}

void MainWindow::startPickCard(quint16 id, quint8 order, CardType _type)
{
    QByteArray buffer;
    buffer.resize(8 + CardTypeSize);
    buffer[0] = 0xAE;
    buffer[1] = CardTypeSize;
    buffer[2] = SendCard;
    buffer[3] = (id >> 8) & 0xff;
    buffer[4] = id & 0xff;
    buffer[5] = order;
    buffer[6] = 0x00;
    buffer[7] = 0x00;
    memcpy(buffer.data() + 8, (char *)&_type, sizeof(CardType));
    transToSocket(buffer);
}

QPixmap MainWindow::makePixmap(CardType _type)
{
    QPixmap pixmap (CARD_WIDTH, CARD_HEIGHT);
    pixmap.fill(Qt::transparent);
    if (_type.point < Card_SJ) {
        QString strFile = QString(":/images/cards/suit_%1%2.png").arg(_type.suit).arg(_type.point < Card_A && _type.point > Card_10 ? 1 : 0);
        QPainter painter(&pixmap);
        painter.setRenderHint(QPainter::SmoothPixmapTransform);
        painter.drawPixmap(0, 0, QPixmap(strFile));
        if (_type.point > Card_10 && _type.point < Card_A) {
            strFile = QString(":/images/cards/card_%1.png").arg(_type.point);
            painter.drawPixmap(0, 0, QPixmap(strFile));
        }
        // 添加数字
        strFile = QString(":/images/cards/num_%1.png").arg(_type.suit % 2);
        QPixmap _pix(strFile);
        painter.drawPixmap(8, 11, _pix.copy(0, 31 * (_type.point - 1), 23, 31));
    }
    else {
        return QPixmap(QString(":/images/cards/card_%1.png").arg(_type.point));
    }

    return pixmap;
}

void MainWindow::setPos(const QPoint &_pos)
{
    m_cardPos = _pos;
    this->update();
}

QPoint MainWindow::cardPos() const
{
    return m_cardPos;
}

void MainWindow::sltPickCard()
{
    m_cardSize--;
    if (m_cards.size() < 4) {
        m_timer->stop();
        ui->widgetPlayBottom->setSort();

        QByteArray buffer = getPackHeader(SendCard, m_cards.size() * CardTypeSize);
        buffer[8] = 0x00;
        int index = 8;
        foreach (QCard *card, m_cards) {
            CardType _type = card->type();
            memcpy(buffer.data() + index, (char *)&_type, CardTypeSize);
            index += CardTypeSize;
            ui->widgetCardShow->addCard(card);
        }

        transToSocket(buffer);
        ui->widgetCardShow->setReady(false);
        ui->stackedWidget->setVisible(true);
        ui->stackedWidget->setCurrentIndex(1);
        this->update();
        return;
    }

    QTime time;
    time = QTime::currentTime();
    qsrand(time.msec() + time.second() * 1000);

    int randomIndex = qrand() % m_cards.size();
    int role = m_cardIndex % 3 + 1;
    m_animation->setStartValue(QPoint(603, 300));
    if (role == ui->widgetPlayBottom->getOrder()) {
        ui->widgetPlayBottom->addCard(m_cards.at(randomIndex));
        m_animation->setEndValue(QPoint(580, 520));
    } else if (role == ui->widgetPlayLeft->getOrder()) {
        ui->widgetPlayLeft->addCard(m_cards.at(randomIndex));
        m_animation->setEndValue(QPoint(240, 330));
    } else if (role == ui->widgetPlayRight->getOrder()) {
        ui->widgetPlayRight->addCard(m_cards.at(randomIndex));
        m_animation->setEndValue(QPoint(940, 330));
    }

    startPickCard(ui->widgetPlayBottom->getUserId(), role, m_cards.at(randomIndex)->type());
    m_cards.removeAt(randomIndex);
    m_cardIndex++;
    m_animation->start();
    this->update();
}

void MainWindow::sltPickLord()
{
    foreach(QCard *card, ui->widgetCardShow->getCards()) {
        QCard *_card = new QCard(card->type(), m_cardPix.value(card->type()));
        _card->setSelected(true);
        ui->widgetPlayBottom->addCard(_card);
    }

    ui->widgetPlayBottom->setRole(Lord);
    ui->widgetPlayBottom->setSort();

#if TEST_UI
    m_alarmClock->move(QPoint(70, 520));
    m_alarmClock->start(10);
#endif
}

void MainWindow::sltPlayCards(HandType _type, CardList _cards)
{
    ui->stackedWidget->setVisible(false);
    ui->widgetAreaCenter->clear();
    ui->widgetAreaCenter->addCards(_cards);
    if (_type == Hand_Bomb) {
        m_animationWidget->setSource(":/images/base/bomb.gif");
    } else if (Hand_Bomb_Jokers == _type) {
        m_animationWidget->setSource(":/images/base/rocket0.png", AnimationWidget::BottomToTop);
    }
    else if (Hand_Plane == _type) {
        m_animationWidget->setSource(":/images/base/plane2.png", AnimationWidget::LeftToRight);
    }

#if TEST_UI
    m_alarmClock->move(QPoint(950, 130));
    m_alarmClock->start(10);
    ui->widgetPlayRight->setHandle(true);
    ui->widgetPlayRight->thinkPlayCars(ui->widgetAreaCenter->getCards(), true);
#endif

    if (m_tcpClient->state() != QTcpSocket::ConnectedState) return;
    QByteArray buffer = getPackHeader(PlayCard, _cards.size() * CardTypeSize);
    buffer[8] = ui->widgetPlayRight->getOrder();
    int index = 9;
    foreach (QCard *card, _cards) {
        CardType _type = card->type();
        memcpy(buffer.data() + index, (char *)&_type, CardTypeSize);
        index += CardTypeSize;
    }

    transToSocket(buffer);
}

void MainWindow::rightPlayCars(HandType _type, CardList _cards)
{
    ui->stackedWidget->setVisible(false);
    ui->widgetAreaCenter->clear();
    if (!_cards.isEmpty()) {
        ui->widgetAreaCenter->addCards(_cards);
    }

    if (_type == Hand_Bomb) {
        m_animationWidget->setSource(":/images/base/bomb.gif");
    } else if (Hand_Bomb_Jokers == _type) {
        m_animationWidget->setSource(":/images/base/rocket1.png", AnimationWidget::BottomToTop);
    }
    else if (Hand_Plane == _type) {
        m_animationWidget->setSource(":/images/base/plane.png", AnimationWidget::LeftToRight);
    }

#if TEST_UI
    m_alarmClock->move(QPoint(240, 130));
    m_alarmClock->start(10);
    ui->widgetPlayLeft->setHandle(true);
    ui->widgetPlayLeft->thinkPlayCars(ui->widgetAreaCenter->getCards(), false);
#endif
}

void MainWindow::leftPlayCars(HandType _type, CardList _cards)
{
    ui->stackedWidget->setVisible(false);
    ui->widgetAreaCenter->clear();
    ui->widgetAreaCenter->addCards(_cards);
    if (_type == Hand_Bomb) {
        m_animationWidget->setSource(":/images/base/bomb.gif");
    } else if (Hand_Bomb_Jokers == _type) {
        m_animationWidget->setSource(":/images/base/rocket2.png", AnimationWidget::BottomToTop);
    }
    else if (Hand_Plane == _type) {
        m_animationWidget->setSource(":/images/base/plane2.png", AnimationWidget::LeftToRight);
    }

#if TEST_UI
    m_alarmClock->move(QPoint(70, 520));
    m_alarmClock->start(10);
    ui->widgetPlayBottom->setHandle(true);
    ui->stackedWidget->setCurrentIndex(1);
    ui->stackedWidget->setVisible(true);
#endif
}

void MainWindow::initCardPixs()
{
#ifdef QT_USE_BIG_IMAGE
    for (int i = (Suit_Begin + 1); i < Suit_End; i++) {
        for (int j = (Card_Begin + 1); j  < Card_SJ; j++)  {
            CardType _type;
            _type.point = (CardPoint)j;
            _type.suit = (CardSuit)i;
            m_cardPix.insert(_type, makePixmap(_type));
        }
    }

    CardType _type;
    _type.point = Card_SJ;
    _type.suit = Suit_Begin;
    m_cardPix.insert(_type, makePixmap(_type));

    _type.point = Card_BJ;
    _type.suit = Suit_Begin;
    m_cardPix.insert(_type, makePixmap(_type));

    _type.point = Card_BG;
    _type.suit = Suit_Begin;
    m_cardPix.insert(_type, makePixmap(_type));
#else
    QPixmap pximap(":/images/cards/default.png");
    for (int i = (Suit_Begin + 1); i < Suit_End; i++) {
        for (int j = (Card_Begin + 1); j  < Card_SJ; j++)  {
            QPixmap _pix = pximap.copy((j - 1) * CARD_WIDTH, (i - 1) * CARD_HEIGHT, CARD_WIDTH, CARD_HEIGHT);
            CardType _type;
            _type.point = (CardPoint)j;
            _type.suit = (CardSuit)i;
            m_cardPix.insert(_type, _pix);
        }
    }

    CardType _type;
    _type.point = Card_SJ;
    _type.suit = Suit_Begin;
    QPixmap _pix = pximap.copy(0, 4 * CARD_HEIGHT, CARD_WIDTH, CARD_HEIGHT);
    m_cardPix.insert(_type, _pix);

    _type.point = Card_BJ;
    _type.suit = Suit_Begin;
    _pix = pximap.copy(CARD_WIDTH, 4 * CARD_HEIGHT, CARD_WIDTH, CARD_HEIGHT);
    m_cardPix.insert(_type, _pix);

    _type.point = Card_BG;
    _type.suit = Suit_Begin;
    _pix = pximap.copy(CARD_WIDTH * 2, 4 * CARD_HEIGHT, CARD_WIDTH, CARD_HEIGHT);
    m_cardPix.insert(_type, _pix);
#endif
}

void MainWindow::initCards()
{
    for (int i = (Suit_Begin + 1); i < Suit_End; i++) {
        for (int j = (Card_Begin + 1); j  < Card_SJ; j++)  {
            CardType _type;
            _type.point = (CardPoint)j;
            _type.suit = (CardSuit)i;
            m_cards.push_back(new QCard(_type, m_cardPix.value(_type)));
        }
    }

    CardType _type;
    _type.point = Card_SJ;
    _type.suit = Suit_Begin;
    m_cards.push_back(new QCard(_type, m_cardPix.value(_type)));

    _type.point = Card_BJ;
    _type.suit = Suit_Begin;
    m_cards.push_back(new QCard(_type, m_cardPix.value(_type)));

    m_timer->start();
    m_cardSize = 54;
}

void MainWindow::resizeEvent(QResizeEvent *e)
{
    m_animationWidget->setGeometry(0, 0, this->width(), this->height());
    QWidget::resizeEvent(e);
}

void MainWindow::on_btnStart_clicked()
{
#if TEST_UI
    ui->widgetPlayLeft->setOrder(3);
    ui->widgetPlayBottom->setOrder(1);
    ui->widgetPlayRight->setOrder(2);
    QTimer::singleShot(500, this, [=]{initCards();});
    ui->stackedWidget->setVisible(false);
    ui->widgetPlayBottom->setReady(true);
    return;
#endif

    QByteArray buffer = getPackHeader(Ready, 0x01);
    buffer[8] = 0x01;
    transToSocket(buffer);
    ui->stackedWidget->setVisible(false);
    ui->widgetPlayBottom->setReady(true);

    if (ui->widgetPlayLeft->isReady() && ui->widgetPlayRight->isReady() && ui->widgetPlayBottom->getOrder() == 1)
    {
        initCards();
    }
}

void MainWindow::on_btnThreeScroe_clicked()
{
    sltPickLord();
    ui->stackedWidget->setCurrentIndex(2);
    ui->stackedWidget->setVisible(true);
    ui->widgetCardShow->setReady(true);

    QByteArray buffer = getPackHeader(Call, 0x02);
    buffer[8] = ui->widgetPlayRight->getOrder();
    buffer[9] = 0x01;
    transToSocket(buffer);
}

void MainWindow::on_btnZeroScore_clicked()
{
    ui->stackedWidget->setVisible(false);

    QByteArray buffer = getPackHeader(Call, 0x02);
    buffer[8] = ui->widgetPlayRight->getOrder();
    buffer[9] = 0x00;
    transToSocket(buffer);
}

void MainWindow::sltSocketConneced()
{
    LoginDialog dlg;
    int ret = dlg.exec();
    if  (0x01 == ret) {
        ui->widgetPlayBottom->setUserId(dlg.getUserId());
        ui->widgetPlayBottom->setOrder(dlg.getDesktopSeq());
        transToSocket(getPackHeader(EnterIn));
    }
}

void MainWindow::sltSockeDisconneced()
{

}

void MainWindow::sltSocketRead()
{
    QByteArray buffer;
    buffer.resize(256);
    unsigned char * br = (unsigned char*)buffer.data();
    int bytesrec;
    unsigned char byt;
    unsigned char len;

    // look for a START
    do {
        bytesrec = m_tcpClient->read((char*)br, 1);
        if (bytesrec <= 0) return;
        byt = br[0];
    } while (byt != 0xAE);

    bytesrec = m_tcpClient->read((char*)br + 1, 1);
    len = br[1];
    bytesrec = m_tcpClient->read((char*)br + 2, 6);
    // 加载后续数据
    if (len > 0) {
        bytesrec = m_tcpClient->read((char*)br + 8, len);
        if (bytesrec < 0 || bytesrec < len) {
            return;
        }
    }

    // 解包
    parseBuffer(buffer.left(len + 8));
}

void MainWindow::sltAlarmTimeout()
{
    static int index = 0;
    const QPoint s_pos[] = {QPoint(240, 130), QPoint(70, 520), QPoint(950, 130)};
    m_alarmClock->move(s_pos[index]);
    index++;
    if (index >= 3) index = 0;
    m_alarmClock->start(10);
}

void MainWindow::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
    painter.drawPixmap(0, 0, QPixmap(":/images/desktop.png"));
    static const QRect s_scorePos[] = {
        QRect(60, 15, 185, 35),
        QRect(540, 670, 185, 35),
        QRect(1075, 15, 185, 35)
    };
    painter.setPen(QColor("#FFF892"));
    QFont font = painter.font();
    font.setPixelSize(30);
    font.setBold(true);
    painter.setFont(font);
    for (int i = 0; i < 3; i++) {
        painter.drawText(s_scorePos[i], Qt::AlignVCenter, QString::number(100000));
    }

    // 发牌动画
    if (m_timer->isActive())
    {
        static QPixmap cardBg = QPixmap(":/images/cards/card_16.png").scaled(CARD_WIDTH * 0.6, CARD_HEIGHT * 0.6, Qt::KeepAspectRatio, Qt::SmoothTransformation);
        int nX = (this->width() - cardBg.width()) / 2;
        int nY = (this->height() - cardBg.height()) / 2 - m_cardSize * 0.2;
        for (int i = 0; i < m_cardSize; i++) {
            painter.drawPixmap(nX, nY - i * 0.2, cardBg);
        }

        painter.drawPixmap(m_cardPos, cardBg);
    }
}

void MainWindow::mouseReleaseEvent(QMouseEvent *e)
{
    if (e->button() == Qt::RightButton) {
#if TEST_UI
        ui->widgetPlayBottom->setHandle(true);
#endif
        ui->widgetPlayBottom->playCards(ui->widgetAreaCenter->getCards(), true);
    }
}

void MainWindow::keyPressEvent(QKeyEvent *e) {
    if (e->key() == Qt::Key_F5 && !m_timer->isActive()) {
#if TEST_UI
        m_cards.clear();
        ui->widgetPlayLeft->clear();
        ui->widgetCardShow->clear();
        ui->widgetAreaCenter->clear();
        ui->widgetPlayRight->clear();
        ui->widgetPlayBottom->clear();
        ui->stackedWidget->setCurrentIndex(0);
        ui->stackedWidget->setVisible(true);
#endif
    }
}
